using System.Collections.Generic;
using UnityEngine;
using UnityEngine.U2D;

public static class XSpriteManager
{
    static readonly Dictionary<string, SpriteAtlas> spriteAtlasDict = new Dictionary<string, SpriteAtlas>();
    
    /// <summary>
    /// loading map
    /// </summary>
    static readonly Dictionary<string, bool> 
        spriteAtlasLoading = new Dictionary<string, bool>();
    
    /// <summary>
    /// loading cache callback
    /// </summary>
    public class SpriteCacheCallback
    {
        public string name;
        public System.Action<Sprite> callback;
    }

    /// <summary>
    /// 
    /// </summary>
    static readonly Dictionary<string, List<SpriteCacheCallback>> callbacks = new Dictionary<string, List<SpriteCacheCallback>>();

    /// <summary>
    /// load sprite
    /// </summary>
    /// <param name="path"></param>
    /// <param name="complete"></param>
    public static void LoadAsync(string path, System.Action<Sprite> complete)
    {
#if UNITY_2019_1_OR_NEWER
        string file = System.IO.Path.GetDirectoryName(path);
        if (!spriteAtlasDict.ContainsKey(file))
        {
            if (!spriteAtlasLoading.ContainsKey(file))
            {
                spriteAtlasLoading.Add(file, true);

                XRes.LoadAsync<SpriteAtlas>(file, (atlas) => {
                    spriteAtlasLoading.Remove(file);

                    SpriteAtlas spriteAtlas = (SpriteAtlas)atlas;
                    if (!spriteAtlas)
                        throw new System.NullReferenceException(file);

                    spriteAtlasDict.Add(file, spriteAtlas);

                    string name = System.IO.Path.GetFileName(path);
                    Sprite sprite = spriteAtlas.GetSprite(name);
                    if (sprite)
                    {
                        complete?.Invoke(sprite);
                    }
                    else
                    {
#if UNITY_EDITOR || UNITY_DEVELOP
                        GLog.LogError("Can't find sprite atlas {0} {1}", file, name);
#endif
                    }

            
                    if (callbacks.ContainsKey(file))
                    {
                        List<SpriteCacheCallback> spriteCallbacks = callbacks[file];
                        foreach (SpriteCacheCallback scc in spriteCallbacks)
                        {
                            sprite = spriteAtlas.GetSprite(scc.name);
                            scc.callback(sprite);
                        }

                        callbacks.Remove(file);
                    }
                });
            }
            else
            {
                if (!callbacks.ContainsKey(file))
                {
                    callbacks.Add(file, new List<SpriteCacheCallback>());
                }

                List<SpriteCacheCallback> cache = callbacks[file];
                cache.Add(new SpriteCacheCallback() {
                    name = System.IO.Path.GetFileName(path), callback=complete
                });
            }
        }
        else
        {
            string name = System.IO.Path.GetFileName(path);
            if (spriteAtlasDict.TryGetValue(file, out SpriteAtlas spriteAtlas))
            {
                Sprite sprite = spriteAtlas.GetSprite(name);
                if (sprite)
                    complete?.Invoke(sprite);
            }
            else
            {
#if UNITY_EDITOR || UNITY_DEVELOP
                GLog.LogError("Can't find sprite atlas {0} {1}", file, name);
#endif
            }
        }
#else
        XRes.LoadAsync<SpriteRenderer>(path, (obj) =>
        {
            SpriteRenderer sr = (SpriteRenderer)obj;
            if (sr)
                complete?.Invoke(sr.sprite);
        });
#endif
    }
}
